package cn.zhoushengdao.eyeprotector

import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.Service
import android.app.usage.UsageStatsManager
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.pm.ServiceInfo
import android.graphics.PixelFormat
import android.os.Build
import android.os.Handler
import android.os.IBinder
import android.os.Looper
import android.util.Log
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.WindowManager
import android.widget.FrameLayout
import android.widget.TextView
import androidx.core.content.ContextCompat
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

class EyeProtectorService : Service() {

    companion object {
        var isServiceRunning = false
        var lastTotalUsageInPeriod: Long = 0
        var previousTipSpace: Long = 0

        private const val NOTIFICATION_ID = 1
        private const val CHANNEL_ID = "eye_protector_channel"

        // 每次休息的时间（秒）
        const val BREAK_SECONDS = 60

        // 每两次休息的最短间隔（分）
        const val SPACE_BETWEEN_TIPS_MINUTES = 20

        // 检查过去多长时间内的使用情况（分）
        const val PAST_USAGE_STATS_CHECK_MINUTES = 40

        // 这段时间内的最长允许使用时间，超出就需要休息（分）
        const val MAX_ALLOWED_USAGE_MINUTES = 20

        // 是否允许当要求休息时使用，true 将会启用点击穿透和 50% 的透明度，false 将会禁用点击穿透和完全不透明
        const val ALLOW_USAGE_WHEN_BREAK = true
    }

    private lateinit var windowManager: WindowManager
    private var overlayView: View? = null
    private var countdownText: TextView? = null
    private val handler = Handler(Looper.getMainLooper())
    private var isOverlayShowing = false
    private var lastInteractionTime = System.currentTimeMillis()
    private var totalUsageInPeriod = 0L
    private var countdownRunnable: Runnable? = null
    private var seconds = BREAK_SECONDS
    private val usageStatsManager by lazy {
        getSystemService(USAGE_STATS_SERVICE) as UsageStatsManager
    }
    private var countdownStartTime: Long = 0
    private var elapsedSecondsBeforePause = 0
    private var isCountdownPaused = false
    private var screenStateReceiver: BroadcastReceiver? = null

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        Log.d("EyeProtector", "EyeProtectorService onStartCommand")
        intent?.let {
            when (it.action) {
                "SHOW_OVERLAY_IMMEDIATELY" -> if (!isOverlayShowing) showOverlay()
                "SHOW_OVERLAY_IF_NECESSARY" -> checkUsageTime(skipBreak = true)
            }
        }
        return START_STICKY
    }

    override fun onCreate() {
        super.onCreate()
        val notification = createNotification()
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
            startForeground(
                NOTIFICATION_ID, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_SPECIAL_USE
            )
        } else {
            startForeground(NOTIFICATION_ID, notification)
        }
        windowManager = getSystemService(WINDOW_SERVICE) as WindowManager
        startUsageMonitoring()
        isServiceRunning = true
        registerScreenStateReceiver()
    }

    private fun createNotification(): Notification {
        val channel = NotificationChannel(
            CHANNEL_ID, "护眼助手", NotificationManager.IMPORTANCE_LOW
        ).apply {
            description = "监控屏幕使用时间"
        }

        val notificationManager = getSystemService(NotificationManager::class.java)
        notificationManager.createNotificationChannel(channel)

        return Notification.Builder(this, CHANNEL_ID).setContentTitle("护眼助手运行中")
            .setContentText("正在监控屏幕使用时间").setSmallIcon(R.drawable.ic_eye_protector)
            .build()
    }

    private fun startUsageMonitoring() {
        // 每分钟检查一次使用情况
        handler.post(usageMonitorRunnable)
    }

    private fun registerScreenStateReceiver() {
        screenStateReceiver = object : BroadcastReceiver() {
            override fun onReceive(context: Context, intent: Intent) {
                when (intent.action) {
                    Intent.ACTION_SCREEN_OFF -> {
                        if (isOverlayShowing) {
                            pauseCountdown()
                        }
                    }

                    Intent.ACTION_USER_PRESENT -> {
                        if (isOverlayShowing && isCountdownPaused) {
                            resumeCountdown()
                        }
                    }
                }
            }
        }

        val filter = IntentFilter().apply {
            addAction(Intent.ACTION_SCREEN_OFF)
            addAction(Intent.ACTION_USER_PRESENT)
        }
        registerReceiver(screenStateReceiver, filter)
    }

    private val usageMonitorRunnable = object : Runnable {
        override fun run() {
            checkUsageTime()
            handler.postDelayed(this, 60 * 1000) // 每分钟执行
        }
    }

    private fun checkUsageTime(skipBreak: Boolean = false) {
        CoroutineScope(Dispatchers.IO).launch {
            val currentTime = System.currentTimeMillis()

            // 计算距上次提醒的时间（分钟）
            previousTipSpace = (currentTime - lastInteractionTime) / (1000 * 60)

            // 检查 PAST_USAGE_STATS_CHECK_MINUTES 分钟内累计使用时间
            val stats = usageStatsManager.queryUsageStats(
                UsageStatsManager.INTERVAL_DAILY,
                currentTime - PAST_USAGE_STATS_CHECK_MINUTES * 60 * 1000,
                currentTime
            )

            // 计算总使用时间（毫秒）
            totalUsageInPeriod = stats?.filter {
                it.lastTimeUsed >= currentTime - PAST_USAGE_STATS_CHECK_MINUTES * 60 * 1000 && it.lastTimeUsed <= currentTime
            }?.sumOf { it.totalTimeInForeground } ?: 0
            lastTotalUsageInPeriod = totalUsageInPeriod / (1000 * 60) // 转换为分钟

            withContext(Dispatchers.Main) {
                if ((previousTipSpace >= SPACE_BETWEEN_TIPS_MINUTES || skipBreak) && lastTotalUsageInPeriod >= MAX_ALLOWED_USAGE_MINUTES) {
                    if (!isOverlayShowing) {
                        showOverlay()
                    }
                }
            }
        }
    }

    private fun showOverlay() {
        val rootContainer = FrameLayout(this)

        val layoutParams = WindowManager.LayoutParams(
            WindowManager.LayoutParams.MATCH_PARENT,
            WindowManager.LayoutParams.MATCH_PARENT,
            WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
            if (ALLOW_USAGE_WHEN_BREAK) {
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN or WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
            } else WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
            PixelFormat.TRANSLUCENT
        ).apply {
            gravity = Gravity.TOP
            alpha = if (ALLOW_USAGE_WHEN_BREAK) 0.5f else 1.0f
        }

        LayoutInflater.from(this).inflate(R.layout.overlay_layout, rootContainer, true)
        overlayView = rootContainer
        countdownText = rootContainer.findViewById(R.id.countdownText)

        overlayView!!.setBackgroundColor(
            ContextCompat.getColor(this, R.color.bg_light)
        )
        countdownText!!.setTextColor(
            ContextCompat.getColor(this, R.color.black)
        )

        windowManager.addView(overlayView, layoutParams)
        isOverlayShowing = true
        startCountdown()
    }

    private fun startCountdown() {
        countdownStartTime = System.currentTimeMillis() // 记录开始时间
        seconds = BREAK_SECONDS
        elapsedSecondsBeforePause = 0
        isCountdownPaused = false

        countdownRunnable = object : Runnable {
            override fun run() {
                if (seconds > 0) {
                    countdownText?.text = seconds.toString()
                    seconds--
                    handler.postDelayed(this, 1000)
                } else {
                    removeOverlay()
                }
            }
        }

        handler.post(countdownRunnable!!)
    }

    private fun pauseCountdown() {
        if (!isCountdownPaused) {
            handler.removeCallbacks(countdownRunnable!!)
            elapsedSecondsBeforePause = seconds
            isCountdownPaused = true
        }
    }

    private fun resumeCountdown() {
        if (isCountdownPaused) {
            // 计算实际经过的时间
            val elapsedMillis = System.currentTimeMillis() - countdownStartTime
            val actualElapsedSeconds = (elapsedMillis / 1000).toInt()

            // 确保不超过 BREAK_SECONDS 秒
            seconds = maxOf(BREAK_SECONDS - actualElapsedSeconds, 0)

            // 如果时间已到，立即移除弹窗
            if (seconds <= 0) {
                removeOverlay()
            } else {
                // 更新 UI 并继续倒计时
                countdownText?.text = seconds.toString()
                handler.post(countdownRunnable!!)
                isCountdownPaused = false
            }
        }
    }

    private fun removeOverlay() {
        if (isOverlayShowing) {
            countdownRunnable?.let { handler.removeCallbacks(it) }
            windowManager.removeView(overlayView)
            overlayView = null
            isOverlayShowing = false
            resetTimers()
        }
    }

    private fun resetTimers() {
        lastInteractionTime = System.currentTimeMillis()
        totalUsageInPeriod = 0
        previousTipSpace = 0
    }

    override fun onDestroy() {
        super.onDestroy()
        screenStateReceiver?.let {
            unregisterReceiver(it)
        }
        removeOverlay()
        handler.removeCallbacksAndMessages(null)
        isServiceRunning = false
    }

    override fun onBind(intent: Intent?): IBinder? = null
}
